package org.example.wumeng.service.impl;

import org.example.wumeng.mapper.T_prescriptionMapper;
import org.example.wumeng.service.T_prescriptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.example.wumeng.pojo.Prescription;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 方剂服务实现类
 * @author wumen
 * @since 2025-01-01
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class T_prescriptionServiceImpl implements T_prescriptionService {

    @Autowired
    private T_prescriptionMapper prescriptionMapper;

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getList(Integer page, Integer size, String name, String category, String source) {
        // 参数验证和默认值设置
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1) {
            size = 10;
        }
        if (size > 100) { // 限制最大查询数量，防止性能问题
            size = 100;
        }

        // 计算偏移量
        int offset = (page - 1) * size;

        try {
            // 查询数据
            List<Prescription> prescriptions = prescriptionMapper.selectWithCondition(name, category, source, offset, size);
            Long total = prescriptionMapper.countWithCondition(name, category, source);

            // 构造返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("data", prescriptions);
            result.put("total", total);
            result.put("page", page);
            result.put("size", size);
            result.put("pages", total > 0 ? (total + size - 1) / size : 0); // 计算总页数

            return result;
        } catch (Exception e) {
            throw new RuntimeException("查询方剂列表失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Prescription getById(Long id) {
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("方剂ID不能为空或小于等于0");
        }

        try {
            Prescription prescription = prescriptionMapper.selectById(id);
            if (prescription == null) {
                throw new RuntimeException("方剂信息不存在，ID: " + id);
            }
            return prescription;
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("查询方剂详情失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Long create(Prescription prescription) {
        // 参数验证
        validatePrescriptionForCreate(prescription);

        // 检查方剂名称是否已存在
        if (isPrescriptionNameExists(prescription.getName(), null)) {
            throw new RuntimeException("方剂名称已存在: " + prescription.getName());
        }

        // 设置创建和更新时间
        LocalDateTime now = LocalDateTime.now();
        prescription.setCreateTime(now);
        prescription.setUpdateTime(now);

        try {
            int result = prescriptionMapper.insert(prescription);
            if (result <= 0) {
                throw new RuntimeException("创建方剂失败，数据库操作返回0");
            }
            return prescription.getId();
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("创建方剂失败: " + e.getMessage(), e);
        }
    }

    @Override
    public void update(Long id, Prescription prescription) {
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("方剂ID不能为空或小于等于0");
        }

        // 检查方剂是否存在
        Prescription existPrescription = prescriptionMapper.selectById(id);
        if (existPrescription == null) {
            throw new RuntimeException("方剂信息不存在，无法更新，ID: " + id);
        }

        // 参数验证
        validatePrescriptionForUpdate(prescription);

        // 检查方剂名称是否已被其他记录使用
        if (isPrescriptionNameExists(prescription.getName(), id)) {
            throw new RuntimeException("方剂名称已被其他记录使用: " + prescription.getName());
        }

        // 设置ID和更新时间，保持原创建时间
        prescription.setId(id);
        prescription.setUpdateTime(LocalDateTime.now());
        prescription.setCreateTime(existPrescription.getCreateTime()); // 保持原创建时间

        try {
            int result = prescriptionMapper.updateById(prescription);
            if (result <= 0) {
                throw new RuntimeException("更新方剂失败，可能记录已被删除");
            }
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("更新方剂失败: " + e.getMessage(), e);
        }
    }

    @Override
    public void delete(Long id) {
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("方剂ID不能为空或小于等于0");
        }

        // 检查方剂是否存在
        Prescription existPrescription = prescriptionMapper.selectById(id);
        if (existPrescription == null) {
            throw new RuntimeException("方剂信息不存在，无法删除，ID: " + id);
        }

        try {
            int result = prescriptionMapper.deleteById(id);
            if (result <= 0) {
                throw new RuntimeException("删除方剂失败，可能记录已被删除");
            }
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("删除方剂失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Long countByCategory(String category) {
        if (!StringUtils.hasText(category)) {
            return 0L;
        }
        try {
            return prescriptionMapper.countWithCondition(null, category, null);
        } catch (Exception e) {
            throw new RuntimeException("统计方剂分类数量失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Long countBySource(String source) {
        if (!StringUtils.hasText(source)) {
            return 0L;
        }
        try {
            return prescriptionMapper.countWithCondition(null, null, source);
        } catch (Exception e) {
            throw new RuntimeException("统计方剂出处数量失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证方剂信息 - 用于创建
     */
    private void validatePrescriptionForCreate(Prescription prescription) {
        if (prescription == null) {
            throw new IllegalArgumentException("方剂信息不能为空");
        }

        validatePrescriptionCommon(prescription);
    }

    /**
     * 验证方剂信息 - 用于更新
     */
    private void validatePrescriptionForUpdate(Prescription prescription) {
        if (prescription == null) {
            throw new IllegalArgumentException("方剂信息不能为空");
        }

        validatePrescriptionCommon(prescription);
    }

    /**
     * 通用方剂信息验证
     */
    private void validatePrescriptionCommon(Prescription prescription) {
        // 必填字段验证
        if (!StringUtils.hasText(prescription.getName())) {
            throw new IllegalArgumentException("方剂名称不能为空");
        }
        if (!StringUtils.hasText(prescription.getCategory())) {
            throw new IllegalArgumentException("方剂分类不能为空");
        }
        if (!StringUtils.hasText(prescription.getComposition())) {
            throw new IllegalArgumentException("药物组成不能为空");
        }
        if (!StringUtils.hasText(prescription.getFunctions())) {
            throw new IllegalArgumentException("功效不能为空");
        }

        // 字段长度验证
        if (prescription.getName().length() > 100) {
            throw new IllegalArgumentException("方剂名称长度不能超过100个字符，当前长度: " + prescription.getName().length());
        }
        if (prescription.getCategory().length() > 50) {
            throw new IllegalArgumentException("方剂分类长度不能超过50个字符，当前长度: " + prescription.getCategory().length());
        }
        if (prescription.getSource() != null && prescription.getSource().length() > 100) {
            throw new IllegalArgumentException("出处长度不能超过100个字符，当前长度: " + prescription.getSource().length());
        }
        if (prescription.getComposition().length() > 1000) {
            throw new IllegalArgumentException("药物组成长度不能超过1000个字符，当前长度: " + prescription.getComposition().length());
        }
        if (prescription.getUsage() != null && prescription.getUsage().length() > 500) {
            throw new IllegalArgumentException("用法用量长度不能超过500个字符，当前长度: " + prescription.getUsage().length());
        }
        if (prescription.getFunctions().length() > 500) {
            throw new IllegalArgumentException("功效长度不能超过500个字符，当前长度: " + prescription.getFunctions().length());
        }
        if (prescription.getIndications() != null && prescription.getIndications().length() > 500) {
            throw new IllegalArgumentException("主治长度不能超过500个字符，当前长度: " + prescription.getIndications().length());
        }
        if (prescription.getAnalysis() != null && prescription.getAnalysis().length() > 1000) {
            throw new IllegalArgumentException("方解长度不能超过1000个字符，当前长度: " + prescription.getAnalysis().length());
        }

        // 内容格式验证
        validatePrescriptionContent(prescription);
    }

    /**
     * 验证方剂内容格式
     */
    private void validatePrescriptionContent(Prescription prescription) {
        // 验证方剂名称格式（不能包含特殊字符）
        String name = prescription.getName().trim();
        if (name.matches(".*[<>\"'&].*")) {
            throw new IllegalArgumentException("方剂名称不能包含特殊字符：< > \" ' &");
        }

        // 验证分类是否在允许的范围内
        String[] allowedCategories = {
                "解表剂", "泻下剂", "和解剂", "清热剂", "温里剂",
                "补益剂", "理气剂", "活血剂", "止血剂", "化痰剂",
                "消导剂", "驱虫剂", "涌吐剂", "收涩剂", "开窍剂", "其他"
        };

        boolean categoryValid = false;
        for (String category : allowedCategories) {
            if (category.equals(prescription.getCategory())) {
                categoryValid = true;
                break;
            }
        }

        if (!categoryValid) {
            throw new IllegalArgumentException("方剂分类不在允许的范围内，请选择正确的分类");
        }
    }

    /**
     * 检查方剂名称是否已存在
     */
    private boolean isPrescriptionNameExists(String name, Long excludeId) {
        if (!StringUtils.hasText(name)) {
            return false;
        }

        try {
            // 这里需要在Mapper中添加一个按名称查询的方法
            // 为了简化，暂时用条件查询来实现
            List<Prescription> existingPrescriptions = prescriptionMapper.selectWithCondition(name, null, null, 0, 1);

            if (existingPrescriptions.isEmpty()) {
                return false;
            }

            // 如果是更新操作，排除当前记录
            if (excludeId != null) {
                return existingPrescriptions.stream()
                        .anyMatch(p -> !p.getId().equals(excludeId) && name.equals(p.getName()));
            }

            // 创建操作，只要有同名记录就返回true
            return existingPrescriptions.stream()
                    .anyMatch(p -> name.equals(p.getName()));

        } catch (Exception e) {
            // 如果查询出错，为了安全起见，假设不存在
            return false;
        }
    }

    /**
     * 批量删除方剂
     * @param ids 方剂ID列表
     */
    public void batchDelete(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new IllegalArgumentException("删除的ID列表不能为空");
        }

        if (ids.size() > 100) {
            throw new IllegalArgumentException("批量删除数量不能超过100条");
        }

        for (Long id : ids) {
            if (id == null || id <= 0) {
                throw new IllegalArgumentException("ID列表中包含无效的ID: " + id);
            }
        }

        try {
            for (Long id : ids) {
                delete(id);
            }
        } catch (Exception e) {
            throw new RuntimeException("批量删除方剂失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据分类获取方剂列表
     * @param category 分类
     * @param limit 限制数量
     * @return 方剂列表
     */
    @Transactional(readOnly = true)
    public List<Prescription> getByCategory(String category, Integer limit) {
        if (!StringUtils.hasText(category)) {
            throw new IllegalArgumentException("分类不能为空");
        }

        if (limit == null || limit <= 0) {
            limit = 10;
        }
        if (limit > 100) {
            limit = 100;
        }

        try {
            return prescriptionMapper.selectWithCondition(null, category, null, 0, limit);
        } catch (Exception e) {
            throw new RuntimeException("根据分类查询方剂失败: " + e.getMessage(), e);
        }
    }

    /**
     * 搜索方剂（支持方剂名称和组成的模糊搜索）
     * @param keyword 关键词
     * @param page 页码
     * @param size 每页大小
     * @return 搜索结果
     */
    @Transactional(readOnly = true)
    public Map<String, Object> search(String keyword, Integer page, Integer size) {
        if (!StringUtils.hasText(keyword)) {
            throw new IllegalArgumentException("搜索关键词不能为空");
        }

        // 参数处理
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1) {
            size = 10;
        }
        if (size > 100) {
            size = 100;
        }

        int offset = (page - 1) * size;

        try {
            // 在名称中搜索
            List<Prescription> prescriptions = prescriptionMapper.selectWithCondition(keyword, null, null, offset, size);
            Long total = prescriptionMapper.countWithCondition(keyword, null, null);

            Map<String, Object> result = new HashMap<>();
            result.put("data", prescriptions);
            result.put("total", total);
            result.put("page", page);
            result.put("size", size);
            result.put("pages", total > 0 ? (total + size - 1) / size : 0);
            result.put("keyword", keyword);

            return result;
        } catch (Exception e) {
            throw new RuntimeException("搜索方剂失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public org.example.wumeng.pojo.Result<List<Prescription>> getByCategory(String category, int page, int size) {
        try {
            // 参数验证
            if (category == null || category.trim().isEmpty()) {
                return org.example.wumeng.pojo.Result.badRequest("分类参数不能为空");
            }
            if (page < 1) page = 1;
            if (size < 1) size = 10;
            if (size > 100) size = 100;

            int offset = (page - 1) * size;
            List<Prescription> prescriptions = prescriptionMapper.selectByCategory(category.trim(), offset, size);
            int totalCount = prescriptionMapper.countByCategory(category.trim());

            return org.example.wumeng.pojo.Result.success(prescriptions, (long) totalCount);
        } catch (Exception e) {
            return org.example.wumeng.pojo.Result.error("查询分类方剂失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public org.example.wumeng.pojo.Result<List<Map<String, Object>>> getCategoryStatistics() {
        try {
            List<Map<String, Object>> statistics = prescriptionMapper.getCategoryStatistics();
            return org.example.wumeng.pojo.Result.success(statistics);
        } catch (Exception e) {
            return org.example.wumeng.pojo.Result.error("获取分类统计失败: " + e.getMessage());
        }
    }
}